/***************************************************************************
 *   Copyright (C) 2006 by Marco Martin                                    *
 *   notmart@gmail.com                                                     *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the Lesser GNU General Public                   *
 *   License as published by the Free Software Foundation;                 *
 *   either version 2 of the License, or (at your option)                  *
 *   any later version.                                                    *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


#include <kglobal.h>
#include <klocale.h>
#include <kconfig.h>
#include <kapplication.h>
#include <kmessagebox.h>
#include <kconfigdialog.h>
#include <kaboutdata.h>
#include <kaboutapplication.h>
#include <kpopupmenu.h>
#include <kkeydialog.h>
#include <kuser.h>
#include <kstandarddirs.h>
#include <kdebug.h>
#include <qstyle.h>


#include "tastymenu.h"
#include "appearance.h"
#include "behaviour.h"



TastyMenu::TastyMenu(const QString& configFile, Type type, int actions, QWidget *parent, const char *name)
  : KPanelApplet(configFile, type, actions, parent, name), numNewApplications(0)
{

    // Get the current application configuration handle
    kConfig = sharedConfig();
    prefSkel = new Prefs(kConfig);
    prefSkel->readConfig();

    kickerConf = KGlobal::config();
    kickerConf->setGroup("buttons");
    _showBigToolTip = kickerConf->readBoolEntry("EnableIconZoom", true);

    button = new TastyButton(this);

    menuHandler = new MenuHandler(this, prefSkel, "MenuHandler", 
                                  prefSkel->isNormalWindow() ?
                                      Qt::WType_Dialog :
                                      Qt::WType_Popup|Qt::WNoAutoErase);

    connect (button, SIGNAL (pressed()), this, SLOT (clickSlot ()));
    connect (menuHandler, SIGNAL(hidden()), this, SLOT(setButtonUp()));
    _menuButtonLabel = prefSkel->menuButtonLabel();
    if(_menuButtonLabel.isEmpty())
      button -> setTextLabel(i18n("Menu"), false);
    else
      button -> setTextLabel(_menuButtonLabel, false);

    button -> setUsesTextLabel(prefSkel->menuButtonLabelType()
                               != Prefs::EnumMenuButtonLabelType::MenuButtonNone);
    button -> setTextPosition(QToolButton::BesideIcon);
    menuTip = new TastyToolTip(button);

    _toolTipTitle = prefSkel->toolTipTitle();

    if( !_toolTipTitle.isEmpty() )
      menuTip->setTitle(_toolTipTitle);

    if( height() >= KIcon::SizeMedium )
      button->setUsesBigPixmap(true);
    else
      button->setUsesBigPixmap(false);

    iconLoader = KGlobal::iconLoader();

    loadMenuButtonIcon();

    button->setAutoRaise(true);

    _newAppsNotification = prefSkel->newAppsNotification();
    if( _newAppsNotification )
    {
      setNewApplicationsMessage(prefSkel->newInstalledApps().count());
      connect( menuHandler, SIGNAL(newApplications(int)),
               this, SLOT(setNewApplicationsMessage(int)));
    }
    setGlobalAccel( prefSkel->overrideAltF1());

    connect( menuHandler, SIGNAL(kickerConfChanged()),
             this, SLOT(updateConfiguration()) );
}


TastyMenu::~TastyMenu()
{
  //delete prefSkel;
  KGlobal::locale()->removeCatalogue("tastymenu");
}

void TastyMenu::loadMenuButtonIcon()
{
  _menuButtonIcon = prefSkel->menuButtonIcon();
  //the tooltip has the same icon as the button
  menuTip->loadIcon( _menuButtonIcon );

  if( prefSkel->menuButtonIconType()
      == Prefs::EnumMenuButtonIconType::IconNone )
  {
    button->setIconSet(QIconSet());
    return;
  }

  if( position() == pTop || position() == pBottom )
    _iconsize = height();
  else if(position() == pLeft || position() == pRight)
    _iconsize = width();

  QPixmap btnPixmap(iconLoader->loadIcon(_menuButtonIcon, KIcon::Panel, _iconsize));
  if( !btnPixmap.isNull() )
    button->setIconSet(btnPixmap);
  else
  {
    kdDebug() << "Failed to load custom icon" << endl;
    button->setIconSet(iconLoader->loadIcon("kmenu", KIcon::Panel, height()));
  }
}

QPoint TastyMenu::menupos(QWidget *widget)
{
 //now should look decent on all positions
 switch( position() )
 {
   case pLeft:
   {
     return QPoint( this->mapToGlobal( this->geometry().topRight() ));
     break;
   }
   case pRight:
   {
     QPoint buttonCoord = this->mapToGlobal(this->geometry().topLeft());
     return QPoint( buttonCoord.x()-widget->width(), buttonCoord.y() );
     break;
   }
   case pTop:
   {
     return QPoint( this->mapToGlobal( this->geometry().bottomLeft() ));
     break;
   }
   default: //pBottom or floating
   {
     QPoint buttonCoord = this->mapToGlobal(this->geometry().topLeft());
     return QPoint( buttonCoord.x(), buttonCoord.y()-widget->height() );
     break;
   }
 }
}

void TastyMenu::clickSlot()
{
  menuTip->hideTip();

  menuHandler->popup(menupos(menuHandler));

  //QTimer::singleShot( 10000, this, SLOT(setButtonUp()) );
}

void TastyMenu::about()
{
  KAboutData data("tastymenu",
                  I18N_NOOP("Tasty Menu"),
                  "1.0.6",
                  I18N_NOOP("KMenu replacement"),
                  KAboutData::License_LGPL_V2,
                  "(c) 2006-2007, Marco Martin",0,0,"mart@notmart.org");

  data.addAuthor("Marco Martin",
                  I18N_NOOP("Maintainer"),
                  "mart@notmart.org",
                  "http://www.notmart.org");

  data.setTranslator(I18N_NOOP("_: NAME OF TRANSLATORS\\nYour names")
               ,I18N_NOOP("_: EMAIL OF TRANSLATORS\\nYour emails"));

  data.addCredit("Yurkovsky Andrey",
                  I18N_NOOP("For the Russian translation"),
                  "anyr@tut.by");
  data.addCredit("Jannick Kuhr",
                  I18N_NOOP("For the German translation"),
                  "jannick.kuhr@kdemail.net");
  data.addCredit("Jesús S Fernández Prieto (xgoan)",
                  I18N_NOOP("For the Spanish translation"),
                  "jesus@infodps.com");
  data.addCredit("Motsyo Vitaliy",
                  I18N_NOOP("For the Ukrainian translation"),
                  "vitalikmotsyo@gmail.com");
  data.addCredit("Laurent Hilsz",
                  I18N_NOOP("For the French translation"),
                  "laurent.hilsz@gmail.com");
  data.addCredit("Tommi Nieminen",
                  I18N_NOOP("For the Finnish translation"),
                  "translator@legisign.org");
  data.addCredit("Matija Šuklje",
                  I18N_NOOP("For the Slovenian translation"),
                  "matija.suklje@rutka.net");
  data.addCredit("Tomasz Argasiński",
                  I18N_NOOP("For the Polish translation"),
                  "targasinski@o2.pl");
  data.addCredit("Ewerton de A. Dutra"
                  I18N_NOOP("For the Polish translation"),
                  "ea.dutra@gmail.com");


  data.addCredit("Oswald Buddenhagen and Stephan Kulow",
                  I18N_NOOP("For the Switch user code from KDM"),
                  "ossi@kde.org and coolo@kde.org");

  data.addCredit("The whole KBFX team",
                 I18N_NOOP("For some inspirations here and there."),
                 "http://www.kbfx.org");

  data.addCredit("Seb Ruiz",
                 I18N_NOOP("For some code taken from Amarok's statistics list view"),
                 "me@sebruiz.net");

  KIconLoader *iconLoader = KGlobal::iconLoader();
  data.setProgramLogo(iconLoader->loadIcon("kmenu", KIcon::Panel).convertToImage());

  KAboutApplication dialog(&data);
  dialog.exec();
}


void TastyMenu::help()
{
  KApplication::kdeinitExec("khelpcenter", "help:/tastymenu");
}


void TastyMenu::preferences()
{
  if(KConfigDialog::showDialog("settings"))
    return;

  Appearance *appearanceDialog = new Appearance(0, "appearance" );
  Behaviour *behaviourDialog = new Behaviour(0, "behaviour" );

  KConfigDialog *dialog = new KConfigDialog(this, "settings", prefSkel,
                                            KDialogBase::Tabbed,
                                            KConfigDialog::Default|
                                            KConfigDialog::Ok|
                                            KConfigDialog::Apply|
                                            KConfigDialog::Cancel );
  dialog->addPage(appearanceDialog, i18n("Appearance"), "appearance" );
  dialog->addPage(behaviourDialog, i18n("Behaviour"), "behaviour" );
  connect( dialog, SIGNAL(settingsChanged()),
           this, SLOT(updateConfiguration()) );
  dialog->show();
}

void TastyMenu::setGlobalAccel( bool global )
{
  globalAccel = new KGlobalAccel(this);
  globalAccel->insert("Toggle Tasty Menu", i18n("Toggle Tasty Menu"),
                      i18n("Toggle Tasty Menu"),
                      0, 0, this, SLOT(clickSlot()));
  globalAccel->readSettings();
  globalAccel->updateConnections();

  //deactivate or reactivate the global alt+f1 shotcut for kmenu
  if( global )
  {
    if( !kickerConf )
      kickerConf = KGlobal::config();

    kickerConf->setGroup("Global Shortcuts");
    QString kmenuShortcut = kickerConf->readEntry("Popup Launch Menu", "default(Alt+F1)");
    if( kmenuShortcut=="none" )
      return;
    QString tastyMenuShortcut = kickerConf->readEntry("Toggle Tasty Menu", "");
    KShortcut shortCutKey(tastyMenuShortcut);
    kickerConf->writeEntry("Popup Launch Menu", "none");
    kickerConf->writeEntry("Toggle Tasty Menu", kmenuShortcut);
    kickerConf->sync();

  }
  else
  {
    if( !kickerConf )
      kickerConf = KGlobal::config();
    kickerConf->setGroup("Global Shortcuts");
    kickerConf->deleteEntry("Popup Launch Menu");
    kickerConf->sync();
  }
}


void TastyMenu::updateConfiguration()
{
  kickerConf->setGroup("buttons");
  _showBigToolTip = kickerConf->readBoolEntry("EnableIconZoom", true);

  menuHandler->updateConfig();
  setGlobalAccel(prefSkel->overrideAltF1());
  _menuButtonLabel = prefSkel->menuButtonLabel();

  if(_menuButtonLabel.isEmpty())
    button -> setTextLabel(i18n("Menu"), false);
  else
    button -> setTextLabel(_menuButtonLabel, false);

  button -> setUsesTextLabel(prefSkel->menuButtonLabelType()
                               != Prefs::EnumMenuButtonLabelType::MenuButtonNone);
  loadMenuButtonIcon();

  _newAppsNotification = prefSkel->newAppsNotification();

  _toolTipTitle = prefSkel->toolTipTitle();

  if( !_toolTipTitle.isEmpty() )
    menuTip->setTitle(_toolTipTitle);
}


void TastyMenu::setNewApplicationsMessage( int number )
{
  if( number <= 0 )
  {
    menuTip ->setMessage("");
  }
  else
    menuTip ->setMessage(i18n("There is one new installed application",
                              "There are %n new installed applications", number));
  /*else if( number == 1)
    menuTip ->setMessage(i18n("There is one new installed application"));
  else
    menuTip ->setMessage(i18n("There are")+" " + QString().setNum(number) +" "+ i18n("new installed applications"));*/

  if( _showBigToolTip && number > numNewApplications )
    menuTip->notify( menupos( menuTip ) );

  numNewApplications = number;
}


int TastyMenu::widthForHeight(int height) const
{
  int buttonWidth = width();
  if( position() == pTop || position() == pBottom )
  {
    button -> setTextPosition(QToolButton::BesideIcon);
    if( prefSkel->menuButtonLabelType()
        != Prefs::EnumMenuButtonLabelType::MenuButtonNone )
      return ((button->fontMetrics()).width(button->textLabel())) + _iconsize + 10;
    else
      return height;
  }
  else
    return buttonWidth;
}

int TastyMenu::heightForWidth(int width) const
{
  int buttonHeight = height();
  if( position() == pLeft || position() == pRight )
  {
    if( prefSkel->menuButtonLabelType()
        != Prefs::EnumMenuButtonLabelType::MenuButtonNone )
    {
      button -> setTextPosition(QToolButton::BelowIcon);
      return ((button->fontMetrics()).height()) + _iconsize + 10;
    }
    else
      return width;
  }
  else
    return buttonHeight;
}

void TastyMenu::resizeEvent(QResizeEvent *e)
{
  int newHeight = e->size().height();
  button->setFixedHeight(newHeight);
  button->setFixedWidth(e->size().width());

  if( newHeight >= KIcon::SizeMedium )
    button->setUsesBigPixmap(true);
  else
    button->setUsesBigPixmap(false);


  loadMenuButtonIcon();
}

void TastyMenu::mousePressEvent(QMouseEvent *e)
{
  menuTip->hideTip();

  if(e->button()==RightButton)
  {
    KPopupMenu menu(this);

    menu.insertTitle("Tasty Menu");
    menu.insertItem(SmallIcon("kmenu"), i18n("&About"), 1);
    menu.insertItem(SmallIcon("help"), i18n("&Help"), 2);
    menu.insertItem(SmallIcon("kmenuedit"), i18n("&Edit Menu"), 3);
    if( _newAppsNotification )
      menu.insertItem(SmallIcon("locationbar_erase"), i18n("&Clear recently installed applications list"), 4);
    menu.insertSeparator();
    menu.insertItem(SmallIcon("configure_shortcuts"), i18n("&Configure Global Shortcuts..."), 5);
    menu.insertItem(SmallIcon("configure"), i18n("&Configure..."), 6);

    int choice = menu.exec(this->mapToGlobal(e->pos()));

    switch( choice )
    {
      case 1:
        about();
        break;

      case 2:
        help();
        break;

      case 3:
        KRun::runCommand ("kmenuedit");
        break;

      case 4:
        menuHandler->clearNewInstalledApplications();
        setNewApplicationsMessage(0);
        menuHandler->slotUpdateApplications();
        break;
      case 5:
      {
        kickerConf->sync();
        KKeyDialog::configure(globalAccel);
        globalAccel->writeSettings(kickerConf);
        globalAccel->updateConnections();
        kickerConf->sync();
        break;
      }
      case 6:
       preferences();
       break;

      default:
        break;
    }
  }
}

void TastyMenu::enterEvent( QEvent * e )
{
  e=e;
  if( _showBigToolTip && !menuHandler->isVisible() )
    menuTip->showTip(menupos(menuTip));

  KPanelApplet::enterEvent(e);
}

void TastyMenu::leaveEvent( QEvent * e )
{
  e=e;
  menuTip->hideTip();

  KPanelApplet::leaveEvent(e);
}

extern "C"
{
    KPanelApplet* init( QWidget *parent, const QString& configFile)
    {
        KGlobal::locale()->insertCatalogue("tastymenu");
        return new TastyMenu(configFile, KPanelApplet::Normal,
                             KPanelApplet::About | KPanelApplet::Help | KPanelApplet::Preferences,
                             parent, "tastymenu");
    }
}
